<?php
/**************************************************************************
 * Lazybones web development framework for PHP 5.1.2 or newer
 *
 * @author      j100002ben(Benjamin Peng) <j100002ben@gmail.com>
 * @copyright   Copyright (c) 2010, New BSD License
 **************************************************************************/

/**
 * 實作MySQLi資料庫操作使用mysql函式庫
 * 
 * @author j100002ben(Benjamin Peng) <j100002ben@gmail.com>
 * @package core.db
 */
class LZ_MySqli implements LZ_IDbDriver {
	
	protected $_link;
	protected $_encoding = 'utf8';
	protected $_lastSql = '';
	protected $_transaction = false;
	protected $_transactionError = false;

	public function __construct() {
		$dbconf = app::conf()->getActiveDbConfig();
		$this->connect($dbconf['DBNAME'],$dbconf['USER'],$dbconf['PASSWORD'],$dbconf['HOST']);
		$this->setEncoding($dbconf['ENCODING']);
	}

	/**
	 * 建立連線
	 * @param string $dbname 資料庫名稱
	 * @param string $user 使用者名稱
	 * @param string $pswd 使用者密碼
	 * @param string $host 主機
	 */
	public function connect($dbname,$user,$pswd,$host){
        $this->_link = new mysqli($host, $user, $pswd, $dbname);
        if ($this->_link->connect_error)
            die('MySqli Connect failed.<br>');
	}

	/**
	 * 開始交易模式
	 */
	public function beginTransaction(){
        $this->_transaction = true;
        $this->_link->autocommit(false);
        
	}

	/**
	 * 結束交易模式
	 */
	public function endTransaction(){
        $success = !$this->_transactionError;
        $this->_transactionError = false;
        $this->_transaction = false;
        if($success)
            $this->_link->commit();
        else
            $this->_link->rollback();
        $this->_link->autocommit(true);
        return $success;
    }

	/**
	 * 查詢
	 * @param string $sql
	 * @return mixed 結果資源
	 */
	public function query($sql){
		$this->_lastSql = $sql;
		$this->_link->query("SET NAMES '".$this->_encoding."'");
        if(!$this->_transaction)
            $this->_link->autocommit(true);
		$res = $this->_link->query($sql);
        if(!$res){
            if (!$this->_transaction) {
                $this->_displayErrorMsg();
                return false;
            }else{
                $this->_transactionError = true;
            }
        }
		return $res;
	}
    
    /**
	 * 查詢
	 * @param string $sql
	 * @return mixed 結果資源
	 */
	public function multi_query($sql){
		$this->_lastSql = $sql;
		$this->_link->query("SET NAMES '".$this->_encoding."'");
        if(!$this->_transaction)
            $this->_link->autocommit(true);
		$res = $this->_link->multi_query($sql);
        if(!$res){
            if (!$this->_transaction) {
                $this->_displayErrorMsg();
                return false;
            }else{
                $this->_transactionError = true;
            }
        }
		return $res;
	}
    
    public function store_result(){
        return $this->_link->store_result();
    }
    
    public function more_results(){
        return $this->_link->more_results();
    }
    
    public function next_result(){
        return $this->_link->next_result();
    }

	/**
	 * 影響列數
	 * @return int
	 */
	public function affectedRows(){
		return $this->_link->affected_rows;
	}

	/**
	 * 關閉連線
	 */
	public function close(&$res){
		$this->_link->close();
	}

	/**
	 * 最後新增ID
	 * @return int
	 */
	public function lastInsertId(){
		return $this->_link->insert_id;
	}

	/**
	 * 回傳搜尋一列結果 - 陣列格式，失敗傳回false
	 * @param mixed $res 結果資源
	 * @param int 類型 0 = associative array , 1 = numeric array , 2 = both
	 * @return array
	 */
	public function fetch($res,$type = 0){
		if (is_object($res)){
			switch($type){
				case 0:
					return $res->fetch_assoc();
					break;
				case 1:
					return $res->fetch_row();
					break;
				case 2:
					return $res->fetch_array();
					break;
			}
			
		}else{
			return false;
		}
	}

	/**
	 * 回傳搜尋一列結果 - 物件格式，失敗傳回false
	 * @param mixed $res 結果資源
	 * @param string 類別名稱
	 * @return object
	 */
	public function fetchObject($res,$className = null){
		if (is_object($res)){
			if(null === $className){
				return $res->fetch_object();
			}else{
				return $res->fetch_object($className);
			}
		}else{
			return false;
		}
	}

	/**
	 * 取得結果總數
	 * @param mixed $res 結果資源
	 * @return int
	 */
	public function count($res){
		if (is_object($res)){
			return $res->num_rows;
		}else{
			return false;
		}
	}

	/**
	 * 跳脫字元格式化
	 * @param string $str 原始字串
	 * @return string
	 */
	public function escape($str){
		return $this->_link->real_escape_string($str);
	}

	/**
	 * 設定編碼方式
	 * @param string $encoding
	 */
	public function setEncoding($encoding){
		$this->_encoding = $encoding;
	}

	/**
	 * 取得最後查詢SQL
	 * @return string
	 */
	public function getLastSql(){
		return $this->_lastSql;
	}

	/**
	 * 顯示錯誤訊息
	 */
	private function _displayErrorMsg(){
		if (app::conf()->DEBUG_MOD){
			$Message = $this->_link->error;
			$Number	= $this->_link->errno;
			$SQL = $this->_lastSql;
			$errMsg = <<<EOD
            Error Message       :$Message<br />
            Error Number        :$Number<br />
            Query SQL           :$SQL
EOD;
		}else{
			$errMsg = "mysqli_query() error.<br>";
		}
		app::throwError($errMsg);
	}
}
